import cv2, imutils
import time
import pyzbar.pyzbar as pyzbar
import numpy as np

# 裁剪
# 宽度是x 顶点向右方向  高度是y ,顶点向下方向
crop_x_min = 0   
crop_x_max = 1000
crop_y_min = 590   
crop_y_max = 1890

kernel_2 = np.ones((2, 2), np.uint8)  # 2x2的卷积核
kernel_3 = np.ones((3, 3), np.uint8)  # 3x3的卷积核
kernel_4 = np.ones((4, 4), np.uint8)  # 4x4的卷积核

draw_color = (0,255,0)

Lower_red = np.array([0, 61, 136])    #red
Upper_red = np.array([5, 255, 255])
draw_red = draw_color
red = [Lower_red, Upper_red, 'red',draw_red]

Lower_blue = np.array([113, 97, 95])
Upper_blue = np.array([120, 189, 225])
draw_blue =draw_color
blue = [Lower_blue, Upper_blue, 'blue',draw_blue]

Lower_green = np.array([39, 60, 133])
Upper_green = np.array([96, 255, 255])
draw_green =draw_color
green = [Lower_green, Upper_green, 'green',draw_green]

Lower_yellow = np.array([21, 103, 63])   
Upper_yellow = np.array([37, 255, 255])
draw_yellow = draw_color
yellow = [Lower_yellow, Upper_yellow, 'yellow',draw_yellow]

Lower_black = np.array([70, 100, 100])
Upper_black = np.array([87, 150, 120])
draw_black = (0,0,0)
black = [Lower_black, Upper_black, 'black',draw_black]

color_list = [red,blue,green,yellow]

class frameClass:

    def color_recong(self,frame):
        #### 转换为灰度图像
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        #### 应用高斯模糊
        blurred = cv2.GaussianBlur(gray, (5, 5), 0)
        #### 检测圆形
        circles = cv2.HoughCircles(blurred, cv2.HOUGH_GRADIENT, 1.2, 100)
        if circles is not None:
            for circle_ in circles[0]:
                mask1 = np.zeros_like(frame)
                x, y, r = int(circle_[0]), int(circle_[1]), int(circle_[2])
                inner_radius = r + 10
                #### 绘制大圆
                cv2.circle(mask1, (x, y), inner_radius, (255, 255, 255), -1)
                outer_circle = cv2.bitwise_and(frame, mask1)
                mask1 = np.zeros_like(frame)
                #### 绘制小圆        
                cv2.circle(mask1, (x, y), r, (255, 255, 255), -1)
                inner_circle_inverse = cv2.bitwise_not(mask1)
                annulus_area = cv2.bitwise_and(outer_circle, inner_circle_inverse)
                
                ##### 把BGR图像转换为HSV格式
                HSV = cv2.cvtColor(annulus_area, cv2.COLOR_BGR2HSV)  
                for color in color_list:
                    mask_red = cv2.inRange(HSV, color[0], color[1])
                    #### 腐蚀 膨胀
                    erosion = cv2.erode(mask_red, kernel_2, iterations=1)   
                    dilation = cv2.dilate(erosion, kernel_4, iterations=1)  
                    #### 二值化，将滤波后的图像变成二值图像放在binary中
                    ret, binary = cv2.threshold(dilation, 0, 255, cv2.THRESH_BINARY)  
                    cnts = cv2.findContours(binary.copy(), cv2.RETR_EXTERNAL,
                                            cv2.CHAIN_APPROX_NONE)
                    cnts = imutils.grab_contours(cnts) 
                    self.max_contour(circle_,cnts,color[2])
                    #### 更新位置
                    self.position[color[2]] = [int(circle_[0]), int(circle_[1]), 0]       
    
    def run(self,):
        #### 通过CV库函数获取视频流数据
        cap = cv2.VideoCapture(9,)
        cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'))  

        while True:  
            ret, self.frame = cap.read()  
            if not ret:
                time.sleep(0.1)
                #### 图像一旦获取失败，不断循环获取图像
                cap = cv2.VideoCapture(9,)
                cap.set(cv2.CAP_PROP_FOURCC,cv2.VideoWriter_fourcc('M','J','P','G'))  
                print("Can't to capture from camera. Exiting ...")  
                break  
            
            #### 图像裁剪--感兴趣区域进行检测
            crop = np.zeros([1944,2592,3],np.uint8)
            crop[crop_x_min:crop_x_max,crop_y_min:crop_y_max] = self.frame[crop_x_min:crop_x_max,crop_y_min:crop_y_max]
            img = crop
            
            #### 二维码检测
            self.color_recong(img)
            time.sleep(0.01)
            
            #### 图像显示与保存
            cv2.imshow('frame', self.frame)
            cv2.imwrite(f"img/crop.png",img)
            cv2.imwrite(f"img/frame.png",self.frame)
        
            # 按下'q'键退出循环  
            if cv2.waitKey(1) & 0xFF == ord('q'):  
                break  

        # 释放摄像头资源  
        cap.release()  
        # 关闭所有OpenCV窗口  
        cv2.destroyAllWindows()

a = frameClass()
a.run()